﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace JXT.PrimaryKey.Batman.ObjectConverter
{
    /// <summary>
    /// 通用对象转换器接口
    /// </summary>
    /// <typeparam name="TSource">源类型</typeparam>
    /// <typeparam name="TResult">目标类型</typeparam>
    public interface IObjectConverter<TSource, TResult>
    {
        /// <summary>
        /// 增加简单属性转换规则
        /// </summary>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <returns>转换器本身</returns>
        IObjectConverter<TSource, TResult> Add(Expression resultPropertyExpression, Expression sourcePropertyExpression);

        /// <summary>
        /// 增加简单属性转换规则
        /// </summary>
        /// <typeparam name="TProperty">属性类型</typeparam>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <returns>转换器本身</returns>
        IObjectConverter<TSource, TResult> Add<TProperty>(Expression<Func<TResult, TProperty>> resultPropertyExpression, Expression<Func<TSource, TProperty>> sourcePropertyExpression);

        /// <summary>
        /// 增加复杂属性转换规则
        /// </summary>
        /// <typeparam name="TSourceProperty">原始属性类型</typeparam>
        /// <typeparam name="TResultProperty">目标属性类型</typeparam>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <param name="converter">复杂属性转换器</param>
        /// <returns>转换器本身</returns>
        IObjectConverter<TSource, TResult> Add<TSourceProperty, TResultProperty>(Expression<Func<TResult, TResultProperty>> resultPropertyExpression,
            Expression<Func<TSource, TSourceProperty>> sourcePropertyExpression,
            IObjectConverter<TSourceProperty, TResultProperty> converter);

        /// <summary>
        /// 增加复杂属性转换规则
        /// </summary>
        /// <typeparam name="TSourceProperty">原始属性类型</typeparam>
        /// <typeparam name="TResultProperty">目标属性类型</typeparam>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <param name="converter">复杂属性转换器</param>
        /// <returns>转换Lambda表达式</returns>
        IObjectConverter<TSource, TResult> Add<TSourceProperty, TResultProperty>(Expression<Func<TResult, TResultProperty>> resultPropertyExpression,
            Expression<Func<TSource, TSourceProperty>> sourcePropertyExpression,
            Expression<Func<TSourceProperty, TResultProperty>> converter);

        /// <summary>
        /// 增加复杂属性转换规则
        /// </summary>
        /// <typeparam name="TSourceProperty">原始属性类型</typeparam>
        /// <typeparam name="TResultProperty">目标属性类型</typeparam>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <param name="converter">转换方法</param>
        /// <returns>转换器本身</returns>
        IObjectConverter<TSource, TResult> AddFunction<TSourceProperty, TResultProperty>(Expression<Func<TResult, TResultProperty>> resultPropertyExpression,
            Expression<Func<TSource, TSourceProperty>> sourcePropertyExpression,
            Func<TSourceProperty, TResultProperty> converter);

        /// <summary>
        /// 增加复杂属性转换规则
        /// </summary>
        /// <typeparam name="TSourceProperty">原始属性类型</typeparam>
        /// <typeparam name="TResultProperty">目标属性类型</typeparam>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <param name="converter">复杂属性转换器</param>
        /// <returns>转换器本身</returns>
        IObjectConverter<TSource, TResult> AddEnumerable<TSourceProperty, TResultProperty>(Expression<Func<TResult, IEnumerable<TResultProperty>>> resultPropertyExpression,
            Expression<Func<TSource, IEnumerable<TSourceProperty>>> sourcePropertyExpression,
            IObjectConverter<TSourceProperty, TResultProperty> converter);

        /// <summary>
        /// 增加复杂属性转换规则
        /// </summary>
        /// <typeparam name="TSourceProperty">原始属性类型</typeparam>
        /// <typeparam name="TResultProperty">目标属性类型</typeparam>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <param name="converter">复杂属性转换器</param>
        /// <returns>转换Lambda表达式</returns>
        IObjectConverter<TSource, TResult> AddEnumerable<TSourceProperty, TResultProperty>(Expression<Func<TResult, IEnumerable<TResultProperty>>> resultPropertyExpression,
            Expression<Func<TSource, IEnumerable<TSourceProperty>>> sourcePropertyExpression,
            Expression<Func<IEnumerable<TSourceProperty>, IEnumerable<TResultProperty>>> converter);

        /// <summary>
        /// 增加复杂属性转换规则
        /// </summary>
        /// <typeparam name="TSourceProperty">原始属性类型</typeparam>
        /// <typeparam name="TResultProperty">目标属性类型</typeparam>
        /// <param name="resultPropertyExpression">目标属性表达式</param>
        /// <param name="sourcePropertyExpression">原始属性表达式</param>
        /// <param name="converter">转换方法</param>
        /// <returns>转换器本身</returns>
        IObjectConverter<TSource, TResult> AddEnumerableFunction<TSourceProperty, TResultProperty>(Expression<Func<TResult, IEnumerable<TResultProperty>>> resultPropertyExpression,
            Expression<Func<TSource, IEnumerable<TSourceProperty>>> sourcePropertyExpression,
            Func<IEnumerable<TSourceProperty>, IEnumerable<TResultProperty>> converter);

        /// <summary>
        /// 执行转换对象操作
        /// </summary>
        /// <param name="source">原始对象</param>
        /// <returns>目标对象</returns>
        TResult Convert(TSource source);

        /// <summary>
        /// 对集合进行转换
        /// </summary>
        /// <param name="sourceEnumerable">源集合</param>
        /// <returns>目标集合</returns>
        IEnumerable<TResult> ConvertEnumerable(IEnumerable<TSource> enumerable);

        /// <summary>
        /// 对集合进行转换
        /// </summary>
        /// <param name="sourceEnumerable">源集合</param>
        /// <returns>目标集合</returns>
        List<TResult> ConvertList(IEnumerable<TSource> sourceEnumerable);
    }
}
